package com.huike.framework.aspectj;

import com.huike.common.annotation.AutoFill;
import com.huike.common.constant.ErrorMessageConstants;
import com.huike.common.constant.MagicConstants;
import com.huike.common.enums.FillType;
import com.huike.common.exception.BaseException;
import com.huike.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @Description 自动填充字段切面类
 * @Author zhuzi
 * @Date 2023/10/15
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * 切面表达式
     */
    @Pointcut("execution(* com.huike.*.service.impl..*(..))&&@annotation(com.huike.common.annotation.AutoFill)")
    public void autoFillPC() {
    }

    /**
     * 自动填充字段
     */
    @Before("autoFillPC()")
    public void autoFill(JoinPoint jp) throws Exception {
        // 获得方法参数
        Object[] args = jp.getArgs();
        if (args == null || args.length == 0) {
            throw new BaseException(ErrorMessageConstants.ANNOTATION_USAGE_ERROR);
        }

        // 准备插入数据
        LocalDateTime ldt = LocalDateTime.now();
        String username = SecurityUtils.getUsername();

        // 获得方法签名
        MethodSignature signature = (MethodSignature) jp.getSignature();

        // 获得注解对象
        AutoFill anno = signature.getMethod().getAnnotation(AutoFill.class);

        // 反射获取方法
        Class<?> clazz = args[0].getClass();
        if (anno.value().equals(FillType.CREATE) || anno.value().equals(FillType.ALL)) {
            Method setCreateTime = clazz.getDeclaredMethod(MagicConstants.SET_CREATE_TIME, LocalDateTime.class);
            setCreateTime.setAccessible(true);
            Method setCreateBy = clazz.getDeclaredMethod(MagicConstants.SET_CREATE_BY, String.class);
            setCreateBy.setAccessible(true);
            setCreateTime.invoke(args[0], ldt);
            setCreateBy.invoke(args[0], username);
        }
        if (anno.value().equals(FillType.UPDATE) || anno.value().equals(FillType.ALL)) {
            Method setUpdateTime = clazz.getDeclaredMethod(MagicConstants.SET_UPDATE_TIME, LocalDateTime.class);
            setUpdateTime.setAccessible(true);
            Method setUpdateBy = clazz.getDeclaredMethod(MagicConstants.SET_UPDATE_BY, String.class);
            setUpdateBy.setAccessible(true);
            setUpdateTime.invoke(args[0], ldt);
            setUpdateBy.invoke(args[0], username);
        }
    }

}
